package top.hcode.hoj.controller.file;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.nutz.lang.Files;
import org.nutz.lang.Strings;
import org.nutz.lang.Times;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import top.hcode.hoj.common.result.CommonResult;
import top.hcode.hoj.dao.common.FileEntityService;
import top.hcode.hoj.pojo.dto.OssFileUploadNotifyDTO;
import top.hcode.hoj.pojo.dto.OssFormUploadDataDTO;
import top.hcode.hoj.pojo.entity.common.File;
import top.hcode.hoj.utils.AliyunOSSUtils;
import top.hcode.hoj.utils.ShiroUtils;

import java.util.concurrent.TimeUnit;

/**
 * @author orangej
 * @since 2024/12/26
 */
@RestController
@RequestMapping("/api/file")
@RequiredArgsConstructor
@Api(tags = "OSS文件上传接口")
public class OssUploadController {
    private final FileEntityService fileEntityService;
    private final StringRedisTemplate redisTemplate;

    @ApiOperation(value = "获取文件上传策略", notes = "上传文件前先获取上传策略，然后使用本接口返回的参数向oss上传文件")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "filename", value = "文件名", required = true),
            @ApiImplicitParam(name = "type", value = "文件后缀名，例如：jpeg、ppt、mp4等", required = true)
    })
    @GetMapping("/oss-upload-policy")
    @RequiresAuthentication
    public CommonResult<OssFormUploadDataDTO> getUploadPolicy(String filename, String type) {
        if (Strings.isBlank(filename) && Strings.isBlank(type)) {
            return CommonResult.errorResponse("文件名和文件后缀不能为空");
        }

        String suffix = Files.getSuffix(filename);
        if (Strings.isBlank(suffix) && Strings.isNotBlank(type)) {
            suffix = StrUtil.subAfter(type, "/", true);
        }
        if (Strings.isBlank(suffix)) {
            return CommonResult.errorResponse("文件后缀不能为空");
        }

        String dir = Times.format("yyyyMMdd", Times.now()) + "/";
        String key = dir + IdUtil.getSnowflakeNextId() + suffix;
        OssFormUploadDataDTO dto = AliyunOSSUtils.generatePostSignature(key);

        // 缓存原始文件名
        redisTemplate.opsForValue().set("origin-name:" + key, filename, 10, TimeUnit.MINUTES);

        return CommonResult.successResponse(dto);
    }

    @ApiOperation(value = "文件上传完成后的回调")
    @PostMapping("/oss-upload-notify")
    @RequiresAuthentication
    public CommonResult<File> ossFileUploaded(@RequestBody @Validated OssFileUploadNotifyDTO dto) {
        String url = dto.getUrl();
        String key = url;
        if (url.startsWith("http")) {
            key = StrUtil.subAfter(url, "com/", true);
        }
        String originName = redisTemplate.opsForValue().get("origin-name:" + key);   // 从redis获取原始文件名

        File file = fileEntityService.saveOssFile(ShiroUtils.getUid(), dto.getType(), url, dto.getSize(), originName);
        return CommonResult.successResponse(file);
    }

}
